package com.ajie.ft_kvdata.sp;

import android.content.SharedPreferences;
import android.os.Build;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.util.Log;

import androidx.annotation.RequiresApi;
import androidx.collection.ArrayMap;

import java.io.File;

/**
 * Created by zhangyingjie on 2020/10/17
 *
 * @function
 */
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class SpLancher {
    private static final String TAG = "SpLancher";
    private static ArrayMap<String, ArrayMap<File, SharedPreferencesImpl>> sSharedPrefsCache;
    private ArrayMap<String, File> mSharedPrefsPaths;
    private File mPreferencesDir;
    private final Object mSync = new Object();
    private String customDir;
    public SharedPreferences getSharedPreferences(String name,String dir, int mode) {
        // At least one application in the world actually passes in a null
        // name.  This happened to work because when we generated the file name
        // we would stringify it to "null.xml".  Nice.
//        if (mPackageInfo.getApplicationInfo().targetSdkVersion <
//                Build.VERSION_CODES.KITKAT) {
//            if (name == null) {
//                name = "null";
//            }
//        }

        customDir = dir;
        mPreferencesDir = new File(customDir);
        File file;
        synchronized (SpLancher.class) {
            if (mSharedPrefsPaths == null) {
                mSharedPrefsPaths = new ArrayMap<>();
            }
            file = mSharedPrefsPaths.get(name);
            if (file == null) {
                file = getSharedPreferencesPath(name);
                mSharedPrefsPaths.put(name, file);
            }
        }
        return getSharedPreferences(file, mode);
    }


    public SharedPreferences getSharedPreferences(File file, int mode) {
//        checkMode(mode);
        SharedPreferencesImpl sp;
        synchronized (SpLancher.class) {
            final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked();
            sp = cache.get(file);
            if (sp == null) {
                sp = new SharedPreferencesImpl(file, mode);
                cache.put(file, sp);
                return sp;
            }
        }
//        if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
//                getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
//            // If somebody else (some other process) changed the prefs
//            // file behind our back, we reload it.  This has been the
//            // historical (if undocumented) behavior.
//            sp.startReloadIfChangedUnexpectedly();
//        }
        return sp;
    }

    private ArrayMap<File, SharedPreferencesImpl> getSharedPreferencesCacheLocked() {
        if (sSharedPrefsCache == null) {
            sSharedPrefsCache = new ArrayMap<>();
        }

        final String packageName = getPackageName();
        ArrayMap<File, SharedPreferencesImpl> packagePrefs = sSharedPrefsCache.get(packageName);
        if (packagePrefs == null) {
            packagePrefs = new ArrayMap<>();
            sSharedPrefsCache.put(packageName, packagePrefs);
        }

        return packagePrefs;
    }


    public File getSharedPreferencesPath(String name) {
        return makeFilename(getPreferencesDir(), name + ".xml");
    }

    private File makeFilename(File base, String name) {
        if (name.indexOf(File.separatorChar) < 0) {
            return new File(base, name);
        }
        throw new IllegalArgumentException(
                "File " + name + " contains a path separator");
    }

    private File getPreferencesDir() {
        synchronized (mSync) {
            if (mPreferencesDir == null) {
                mPreferencesDir = new File(getDataDir(), "shared_prefs");
            }
            return ensurePrivateDirExists(mPreferencesDir);
        }
    }

    public File getDataDir() {
        
        return new File(customDir);
        // TODO: 2020/10/17 保护性代码 检查Dir 是否合理 
//        if (mPackageInfo != null) {
//            File res = null;
//            if (isCredentialProtectedStorage()) {
//                res = mPackageInfo.getCredentialProtectedDataDirFile();
//            } else if (isDeviceProtectedStorage()) {
//                res = mPackageInfo.getDeviceProtectedDataDirFile();
//            } else {
//                res = mPackageInfo.getDataDirFile();
//            }
//
//            if (res != null) {
//                if (!res.exists() && android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
//                    /// M: ALPS02821061 and ALPS02819381
//                    ///    Suppress WTF due to data/android directory doesn't exist sometimes
//                    ///    should be expected. Frameworks and apps should take care of the
//                    ///    scenario. @{
//                    Log.e(TAG, "Data directory doesn't exist for package " + getPackageName(),
//                            new Throwable());
//                    /// @}
//                }
//                return res;
//            } else {
//                throw new RuntimeException(
//                        "No data directory found for package " + getPackageName());
//            }
//        } else {
//            throw new RuntimeException(
//                    "No package details found for package " + getPackageName());
//        }
    }

    public String getPackageName() {
        // TODO: 2020/10/17  
        return customDir;
//        if (mPackageInfo != null) {
//            return mPackageInfo.getPackageName();
//        }
//        // No mPackageInfo means this is a Context for the system itself,
//        // and this here is its name.
//        return "android";
    }

    /**
     * Common-path handling of app data dir creation
     */
    private static File ensurePrivateDirExists(File file) {
        if (!file.exists()) {
            try {
                Os.mkdir(file.getAbsolutePath(), 0771);
                Os.chmod(file.getAbsolutePath(), 0771);
            } catch (ErrnoException e) {
                if (e.errno == OsConstants.EEXIST) {
                    // We must have raced with someone; that's okay
                } else {
                    Log.w(TAG, "Failed to ensure " + file + ": " + e.getMessage());
                }
            }
        }
        return file;
    }
}
